package com.yyfax.pay.depository.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.exception.PayExceptionCode;
import com.yyfax.pay.common.util.FuiouIdUtils;
import com.yyfax.pay.depository.vo.BalanceQueryVO;
import com.yyfax.pay.depository.vo.FuiouResponseVO;
import com.yyfax.pay.service.depository.BalanceQueryService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouDepositService;
import com.yyfax.pay.third.facade.fuioudeposit.FuiouSignService;
import com.yyfax.pay.third.model.to.fuioudeposit.BalanceQueryResultXMLRsp;
import com.yyfax.pay.third.model.to.fuioudeposit.BalanceQueryResultXMLRsp.BalancePlain;
import com.yyfax.pay.third.model.to.fuioudeposit.BalanceQueryResultXMLRsp.BalanceQueryRst;
import com.yyfax.pay.third.model.to.fuioudeposit.FuiouDepositConfigExt;
import com.yyfax.pay.vo.depository.BalanceQueryReq;
import com.yyfax.pay.vo.depository.BalanceQueryRsp;

/**
 * 余额查询服务实现
 * 
 * @author heizq
 * @date 2017-09-08 14:20:32
 * @since v1.0.0
 */
@Service
public class BalanceQueryServiceImpl implements BalanceQueryService {

	Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	private FuiouDepositService fuiouDepositService;

	@Resource
	private FuiouSignService fuiouSignService;

	@Resource
	private FuiouIdUtils fuiouIdUtils;

	@Override
	public List<BalanceQueryRsp> balanceQuery(String merchantCode, BalanceQueryReq req) throws Exception {
		final String op = "BalanceQueryServiceImpl.balanceQuery";

		// 1.封装请求参数
		FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(merchantCode);
		BalanceQueryVO vo = buildReqParams(req, extInfo, merchantCode);

		// 2.发请求
		FuiouResponseVO resp = fuiouDepositService.postForResponseVO(vo, extInfo.getQueryBalanceUrl(), merchantCode);

		// 3.检验返回
		checkQueryResult(resp, merchantCode);
		
		// 4.查询结果处理
		BalanceQueryResultXMLRsp rsp = BalanceQueryResultXMLRsp.fromXml(resp.getContent());
		List<BalanceQueryRsp> result = buildResult(rsp);

		logger.info(Log.op(op).msg("【富友存管-余额查询】成功!").toString());
		return result;
	}

	/**
	 * 封装请求
	 * 
	 * @author heizq
	 * @date 2017-09-02 13:30:50
	 * @since v1.0.0
	 * @param domain
	 * @param extInfo
	 * @return
	 */
	private BalanceQueryVO buildReqParams(BalanceQueryReq req, FuiouDepositConfigExt extInfo, String merchantCode) {
		BalanceQueryVO vo = new BalanceQueryVO();
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setMerchantSerialNo(System.currentTimeMillis() + "");
		vo.setTradeDate(DateUtil.date2Str(new Date(), "yyyMMdd"));
		vo.setAccountNo(Joiner.on("|").join(req.getAccountNos()));
		vo.setSignature(fuiouSignService.getSign(merchantCode, vo));
		return vo;
	}

	/**
	 * 解析响应结果
	 * 
	 * @author heizq
	 * @date 2017-09-04 11:38:48
	 * @since v1.0.0
	 * @param rsp
	 * @param merchantCode 商户号
	 * @param busiId 业务主键
	 */
	private void checkQueryResult(FuiouResponseVO resp, String merchantCode) {
		if (FuiouResponseVO.TIMEOUT.equals(resp.getResult())) {
			// 如果请求超时
			throw PayExceptionCode.WARN_REQ_TIME_OUT.exp();
		}

		if (!FuiouResponseVO.NORMAL.equals(resp.getResult())) {
			// 如果查询异常，则直接抛出
			throw PayExceptionCode.QUERY_ERROR.exp();
		}
	}
	
	/**
	 * 封装返回
	 * 
	 * @author heizq
	 * @date 2017-09-08 15:06:45
	 * @since v1.0.0
	 * @param rsp
	 * @return
	 */
	private List<BalanceQueryRsp> buildResult(BalanceQueryResultXMLRsp rsp) {
		BalancePlain plain = rsp.getPlain();
		List<BalanceQueryRst> results = plain.getResults();
		if (results == null || results.size() <= 0) {
			return null;
		}
		
		List<BalanceQueryRsp> queryRsps = Lists.newArrayList();
		for (BalanceQueryRst rst : results) {
			BalanceQueryRsp qeuryRsp = new BalanceQueryRsp();
			qeuryRsp.setAccountNo(rst.getAccountNo());
			qeuryRsp.setAvailBalance(StringUtils.isBlank(rst.getAvailBalance()) ? BigDecimal.ZERO : new BigDecimal(rst.getAvailBalance()));
			qeuryRsp.setBalance(StringUtils.isBlank(rst.getBalance()) ? BigDecimal.ZERO : new BigDecimal(rst.getBalance()));
			qeuryRsp.setFrozenAmount(StringUtils.isBlank(rst.getFrozenAmount()) ? BigDecimal.ZERO : new BigDecimal(rst.getFrozenAmount()));
			qeuryRsp.setOnWayAmount(StringUtils.isBlank(rst.getOnWayAmount()) ? BigDecimal.ZERO : new BigDecimal(rst.getOnWayAmount()));
			queryRsps.add(qeuryRsp);
		}

		return queryRsps;
	}
}
